home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / parsestmt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  25.8 KB  |  940 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /*
  30.  * Harvest C
  31.  * 
  32.  * Copyright 1991 Eric W. Sink   All rights reserved.
  33.  * 
  34.  * This file contains the parser for statements.
  35.  * 
  36.  */
  37.  
  38.  
  39. #include "conditcomp.h"
  40. #include <stdio.h>
  41. #include <string.h>
  42.  
  43. #include "structs.h"
  44. #include "as.h"
  45. #include "lookup.h"
  46. #include "regs.h"
  47.  
  48. #pragma segment ParseStmt
  49.  
  50.  
  51. /* THEPARSER */
  52.  
  53. /*
  54.  * Parsing:  We conceptually separate parsing into 2 stages : syntactic
  55.  * parsing and semantic parsing.  During syntactic parsing, we wish to
  56.  * identify all problems occuring in syntax only - such as unmatched parens.
  57.  * During semantic parsing, we wish to identify all other problems which will
  58.  * prohibit us from producing assembler output.  These problems include : use
  59.  * of an undefined identifier, type mismatches, etc...
  60.  */
  61. /*
  62.  * This compiler does not implement volatile.
  63.  */
  64.  
  65. /*
  66.  * Every routine which returns an expression, must set the type of that
  67.  * expression and whether or not it is an lvalue.  In fact, any such routine
  68.  * should have the following four items, for every call to BuildTree*().  1.
  69.  * The BuildTree*() call itself, 2.  Explicit setting of the type, 3.
  70.  * Explicit setting of the LValue status, and 4.  a TYPERULE comment,
  71.  * explaining what the rules behind that set were.  TYPERULE comments may
  72.  * also explain limitations on operands and the like.
  73.  */
  74.  
  75. #ifdef INLINEASM
  76.  
  77. LocAMVia_t
  78. Do_asm_operand(void)
  79. {                /* TODO This routine not done */
  80.     LocAMVia_t                      result = NULL;
  81.     if (NextIs('#')) {
  82.     if (NextIs(INTCONSTANT)) {
  83.         result = BuildImmediate(LastIntegerConstant, M68sz_long);
  84.     } else {
  85.         SyntaxError("Immediate what ?!?");
  86.     }
  87.     } else if (NextIs('{')) {
  88.     /* FIELD, DYNK, STATK */
  89.     } else if (NextIs('(')) {
  90.     /* Could be almost anything */
  91.     if (NextIs('[')) {
  92.     } else {
  93.         if (GetIDENTIFIER()) {
  94.         /* Need more cases here... */
  95.         }
  96.     }
  97.     } else if (NextIs('-')) {
  98.     if (NextIs('(')) {
  99.         if (GetIDENTIFIER()) {
  100.         result = BuildARegPreDec(LastToken[1] - '0');
  101.         if (!NextIs(')'))
  102.             SyntaxError("Bad asm operand");
  103.         } else {
  104.         SyntaxError("Bad asm operand");
  105.         }
  106.     } else {
  107.         SyntaxError("Bad asm operand");
  108.     }
  109.     } else if (GetIDENTIFIER()) {
  110.     /* We first lookup to see if it's a register name */
  111.     int                             ndx = 0;
  112.     int                             found = 0;
  113.     while (!found && (iregs[ndx].r_name)) {
  114.         if (!strcmp(LastToken, iregs[ndx].r_name)) {
  115.         found = ndx;
  116.         }
  117.         ndx++;
  118.     }
  119.     if (found) {
  120.         result = RawLocation();
  121.         Via(result)->AM = M68am_OtherFormat;
  122.         Via(result)->OtherFormat = Ealloc(sizeof(struct ea));
  123.         Via(Via(result)->OtherFormat)->type = iregs[found].r_type;
  124.         Via(Via(result)->OtherFormat)->reg = iregs[found].r_value;
  125.     } else {
  126.         /* Lookup to see if it's a C identifier */
  127.         SYMVia_t                        symbol;
  128.         symbol = LookUpSymbol(LastToken);
  129.         if (symbol) {
  130.         result = RawLocation();
  131.         Via(result)->AM = M68am_CIdentifier;
  132.         /* TODO */
  133.         }
  134.     }
  135.     } else if (NextIs(INTCONSTANT)) {
  136.     /* Indexed ?? */
  137.     /* TODO Indexed parsing */
  138.     long                            offset = LastIntegerConstant;
  139.     if (NextIs('(')) {
  140.         /* Info from do_indexed() */
  141.         result = RawLocation();
  142.         Via(result)->Constant = offset;
  143.     }
  144.     }
  145.     return result;
  146. }
  147.  
  148. ParseTreeVia_t
  149. Do_assembler_statement(void)
  150. {
  151.     /* asm { list of instructions } */
  152.     /* Each instruction must be terminated in a semicolon */
  153.     ParseTreeVia_t                  result;
  154.     struct mne                     *mneop;
  155.     enum Size68                     SZ = M68sz_none;
  156.     LocAMVia_t                      loc1 = NULL;
  157.     LocAMVia_t                      loc2 = NULL;
  158.     LocAMVia_t                      loc3 = NULL;
  159.     int                             done = 0;
  160.     result = NULL;
  161.     if (NextIs(ASM)) {
  162.     if (!NextIs('{'))
  163.         SyntaxError("Asm must be followed by a bracket");
  164.     result = BuildTreeNode(PTF_asm_stmt, NULL, NULL, NULL);
  165.     Via(result)->data.AsmCodes = RawInstructionList();
  166.     while (!done) {
  167.         LexerGetLine(asmLine);
  168.         if (parse_line()) {
  169.         if (!process_inlineasm(Via(result)->data.AsmCodes))
  170.             done = 1;
  171.         } else
  172.         done = 1;
  173.     }
  174.     PushSRC();
  175.     CurrentSRC.isIO = 0;
  176.     CurrentSRC.where.mem = asmLine;
  177.     if (!NextIs('}'))
  178.         SyntaxError("Asm must be followed by a bracket");
  179.     }
  180.     return result;
  181. }
  182.  
  183. #endif
  184.  
  185. ParseTreeVia_t
  186. Do_statement(void)
  187. {
  188.     /*
  189.      * statement : expression_statement | labeled_statement |
  190.      * compound_statement | assembler_statement | selection_statement |
  191.      * iteration_statement | jump_statement ;
  192.      */
  193.  
  194.     /*
  195.      * No nodes need to be built here.  Each of the types of statements,
  196.      * identifies itself adequately.
  197.      */
  198.     ParseTreeVia_t                  result;
  199.     int                             StartLine;
  200.     StartLine = CurrentSRC.LineCount;
  201.     if (result = Do_labeled_statement()) {
  202.     } else if (result = Do_expression_statement()) {
  203.     } else if (result = Do_compound_statement(NULL)) {
  204. #ifdef INLINEASM
  205.     } else if (result = Do_assembler_statement()) {
  206. #endif
  207.     } else if (result = Do_selection_statement()) {
  208.     } else if (result = Do_iteration_statement()) {
  209.     } else if (result = Do_jump_statement()) {
  210.     } else {
  211.     result = NULL;
  212.     }
  213.     if (result) {
  214.     CurrentSRC.StmtCount++;
  215. #ifdef Undefined
  216.     /* This was removed 28 April 1992.  It has been the cause of a number
  217.     of bugs, and I don't think it provides all that much benefit when
  218.     it's working. */
  219.     result = Constify(result);
  220. #endif
  221.     }
  222.     return result;
  223. }
  224.  
  225. ParseTreeVia_t
  226. Do_labeled_statement(void)
  227. {
  228.     /*
  229.      * labeled_statement : IDENTIFIER ':' statement | CASE constant_expr ':'
  230.      * statement | DEFAULT ':' statement ;
  231.      */
  232.  
  233.     ParseTreeVia_t                  result = NULL;
  234.     if (NextIs(IDENTIFIER)) {
  235.     char                            theid[128];
  236.     strcpy(theid, LastToken);
  237.     if (NextIs(':')) {
  238.         result = Do_statement();
  239.         if (result) {
  240.         SYMVia_t                        label;
  241.         result = BuildIDTreeNode(PTF_labelled_stmt, result, NULL, NULL, theid);
  242.         label = TableSearch(CurrentLabels(), (theid));
  243.         if (!label) {
  244.             label = TableAdd(CurrentLabels(), (theid));
  245.         }
  246.         Via(label)->Definition.Stmt = result;
  247.         } else {
  248.         SyntaxError("Expected statement following label");
  249.         }
  250.     } else {
  251.         /*
  252.          * This is not an error, because the identifier is probably the
  253.          * beginning of an expression.  Labelled statements are parsed
  254.          * before expression statements for this reason.
  255.          */
  256.         PutBackToken(theid, IDENTIFIER);
  257.         result = NULL;
  258.     }
  259.     } else if (NextIs(CASE)) {
  260.     ParseTreeVia_t                  tmp2;
  261.     FunctionComplexity++;
  262.     if (!LastSwitchExpression) {
  263.         SyntaxError("case found outside of switch statement");
  264.     }
  265.     tmp2 = Do_constant_expr();
  266.     if (tmp2) {
  267.         /*
  268.          * TODO Compare type here with that of the expr in
  269.          * LastSwitchExpression.
  270.          */
  271.         if (NextIs(':')) {
  272.         result = Do_statement();
  273.         if (result) {
  274.             result = BuildTreeNode(PTF_switchcase_stmt, tmp2, result, NULL);
  275.         } else {
  276.             SyntaxError("Expected statement following case label");
  277.         }
  278.         } else {
  279.         SyntaxError("Expected ':' after case constant");
  280.         }
  281.     } else {
  282.         SyntaxError("Expected constant expr for case label");
  283.     }
  284.     } else if (NextIs(DEFAULT)) {
  285.     FunctionComplexity++;
  286.     if (!LastSwitchExpression) {
  287.         SyntaxError("default found outside of switch statement");
  288.     }
  289.     if (NextIs(':')) {
  290.         result = Do_statement();
  291.         if (result) {
  292.         result = BuildTreeNode(PTF_switchdefault_stmt, result, NULL, NULL);
  293.         } else {
  294.         SyntaxError("Expected statement following default label");
  295.         }
  296.     } else {
  297.         SyntaxError("default must be followed by a colon");
  298.     }
  299.     } else {
  300.     result = NULL;
  301.     }
  302.     return result;
  303. }
  304.  
  305. ParseTreeVia_t
  306. Do_compound_statement(SYMVia_t functop)
  307. {
  308.     /*
  309.      * compound_statement : '{' '}' | '{' statement_list '}' | '{'
  310.      * declaration_list '}' | '{' declaration_list statement_list '}' ;
  311.      */
  312.  
  313.     ParseTreeVia_t                  result;
  314.     int                             declresult;
  315.     ScopesVia_t                     thescopes;
  316.     if (NextIs('{')) {
  317.     ParseTreeVia_t                  tmp;
  318.     ExtraBlocks = 0;
  319.     if (functop) {
  320.         if (GetTPKind(Via(functop)->TP) == TRC_typedef) {
  321.         DeclError("A function cannot gain that status by means of typedef");
  322.         }
  323.     }
  324.     result = BuildTreeNode(PTF_compound_stmt, NULL, NULL, NULL);
  325.     SetTreeScopes(result, thescopes = Ealloc(sizeof(Scopes_t)));
  326.     Via(thescopes)->Symbols = RawTable(11);
  327.     Via(thescopes)->Tags = RawTable(11);
  328.     Via(thescopes)->Enums = NULL;
  329.     if (functop) {
  330.         Via(thescopes)->Labels = RawTable(11);
  331.         PushSpaces(GetTPMembers(Via(functop)->TP), NULL, NULL);    /* function parameters */
  332.     } else {
  333.         Via(thescopes)->Labels = NULL;    /* We don't push a table
  334.                          * here, thus keeping the
  335.                          * previous scope level for
  336.                          * labels, because the scope
  337.                          * of a label is the entire
  338.                          * function in which it
  339.                          * resides.  The label table
  340.                          * for each function is
  341.                          * pushed only once. */
  342.     }
  343.     PushSpaces(Via(thescopes)->Symbols,
  344.            Via(thescopes)->Tags,
  345.            Via(thescopes)->Labels);
  346.     if (NextIs('}')) {
  347.         if (ExtraBlocks) {
  348.             while (ExtraBlocks--)
  349.             PopBlock();
  350.         }
  351.         PopBlock();
  352.         if (functop) {
  353.         PopBlock();
  354.         }
  355.         UserWarning(WARN_emptycompound);
  356.     } else {
  357.         char                            nm[64];
  358.         declresult = Do_declaration_list(Via(thescopes)->Symbols);
  359.         if (functop) {
  360.         /*
  361.          * Check all members of the just-parsed declaration list, to
  362.          * make sure there are no conflicts with declared args
  363.          */
  364.         int                             ndx;
  365.         SYMVia_t                        cur;
  366.         ndx = Via(Via(thescopes)->Symbols)->count;
  367.         while (ndx) {
  368.             cur = TableGetNum(Via(thescopes)->Symbols, ndx);
  369.             GetSymName(cur, nm);
  370.             if (TableSearch(GetTPMembers(Via(functop)->TP), nm)) {
  371.             DeclError("Local variable conflicts with parameter");
  372.             }
  373.             ndx--;
  374.         }
  375.         }
  376.         tmp = Do_statement_list();
  377.         CheckUsages(Via(thescopes)->Symbols);
  378.         if (ExtraBlocks) {
  379.             while (ExtraBlocks--)
  380.                 PopBlock();
  381.         }
  382.         PopBlock();
  383.         if (functop) {
  384.         PopBlock();
  385.         }
  386.         if (declresult) {
  387.         if (tmp) {
  388.             Via(result)->a = tmp;
  389.             if (!NextIs('}')) {
  390.             SyntaxError("Missing right brace");
  391.             }
  392.         } else {
  393.             if (!NextIs('}')) {
  394.             SyntaxError("Missing right brace");
  395.             }
  396.         }
  397.         } else if (tmp) {
  398.         Via(result)->a = tmp;
  399.         if (!NextIs('}')) {
  400.             SyntaxError("Missing right brace");
  401.         }
  402.         } else {
  403.         SyntaxError("Missing right brace");
  404.         }
  405.     }
  406.     } else {
  407.     result = NULL;
  408.     }
  409.     return result;
  410. }
  411.  
  412. int
  413. isJumpStmt(ParseTreeVia_t tree)
  414. {
  415.     if (!tree) {
  416.     return 0;
  417.     }
  418.     switch (Via(tree)->kind) {
  419.     case PTF_goto_stmt:
  420.     case PTF_break_stmt:
  421.     case PTF_continue_stmt:
  422.     case PTF_return_stmt:
  423.     return 1;
  424.     break;
  425.     default:
  426.     return 0;
  427.     break;
  428.     }
  429. }
  430.  
  431. int
  432. isLabeledStmt(ParseTreeVia_t tree)
  433. {
  434.     if (!tree) {
  435.     return 0;
  436.     }
  437.     switch (Via(tree)->kind) {
  438.     case PTF_labelled_stmt:
  439.     case PTF_switchcase_stmt:
  440.     case PTF_switchdefault_stmt:
  441.     return 1;
  442.     break;
  443.     default:
  444.     return 0;
  445.     break;
  446.     }
  447. }
  448.  
  449. ParseTreeVia_t
  450. Do_statement_list(void)
  451. {
  452.     /*
  453.      * statement_list : statement | statement_list statement ;
  454.      */
  455.     ParseTreeVia_t                  result;
  456.     int                             donelisting;
  457.     int                             lastwasjump;
  458.     result = Do_statement();
  459.     if (result) {
  460.     lastwasjump = isJumpStmt(result);
  461.     donelisting = 0;
  462.     while (!donelisting) {
  463.         ParseTreeVia_t                  tmp;
  464.         tmp = Do_statement();
  465.         if (tmp) {
  466.         if (lastwasjump && isLabeledStmt(tmp)) {
  467.             lastwasjump = 0;
  468.         }
  469.         if (lastwasjump && !isLabeledStmt(tmp)) {
  470.             UserWarning(WARN_deadcode);
  471.             /* TODO We should consider removal of the dead code. */
  472.         }
  473.         result = BuildTreeNode(PTF_stmt_list, tmp, result, NULL);
  474.         /*
  475.          * Here is an example of a parse tree list. We want to be
  476.          * sure that whatever gets returned from this routine has a
  477.          * valid statement in a, and an optional tail of list in b.
  478.          * In other words, when constructing a list, the tail should
  479.          * always be in b, not a.
  480.          */
  481.         } else {
  482.         donelisting = 1;
  483.         }
  484.     }
  485.     }
  486.     return result;
  487. }
  488.  
  489. /*----------------------------------------*/
  490.  
  491. ParseTreeVia_t
  492. Do_expression_statement(void)
  493. {
  494.     /*
  495.      * expression_statement : ';' | expr ';' ;
  496.      */
  497.  
  498.     ParseTreeVia_t                  result;
  499.     result = NULL;
  500.     if (NextIs(';')) {
  501.     result = BuildTreeNode(PTF_emptystmt, NULL, NULL, NULL);
  502.     UserWarning(WARN_emptystatement);
  503.     } else {
  504.     result = Do_expr();
  505.     if (result) {
  506.         if (Via(result)->kind == PTF_function_call) {
  507.         if (!isVoidType(GetTreeTP(result))) {
  508.             UserWarning(WARN_discardfuncresult);
  509.         }
  510.         }
  511.         result = BuildTreeNode(PTF_exprstmt, result, NULL, NULL);
  512.         if (!NextIs(';')) {
  513.         SyntaxError("Missing semicolon");
  514.         }
  515.     }
  516.     }
  517.     return result;
  518. }
  519.  
  520. ParseTreeVia_t
  521. Do_selection_statement(void)
  522. {
  523.     /*
  524.      * selection_statement : IF '(' expr ')' statement | IF '(' expr ')'
  525.      * statement ELSE statement | SWITCH '(' expr ')' statement ;
  526.      */
  527.  
  528.     ParseTreeVia_t                  result = NULL;
  529.     ParseTreeVia_t                  tmp;
  530.     FoldValue_t                     testK;
  531.     if (NextIs(IF)) {
  532.     FunctionComplexity++;
  533.     if (NextIs('(')) {
  534.         tmp = Do_expr();
  535.         if (tmp) {
  536.         if (Via(tmp)->kind == PTF_assign) {
  537.             UserWarning(WARN_assignif);
  538.         }
  539.         ConstExprValue(tmp, &testK);
  540.         if (testK.isK) {
  541.             UserWarning(WARN_constantif);
  542.         }
  543.         if (!isBooleanType(GetTreeTP(tmp))) {
  544.             TypeError("if expression must be arithmetic or pointer type");
  545.         }
  546.         if (NextIs(')')) {
  547.             result = Do_statement();
  548.             if (result) {
  549.             if (NextIs(ELSE)) {
  550.                 ParseTreeVia_t                  tmp2;
  551.                 FunctionComplexity++;
  552.                 tmp2 = Do_statement();
  553.                 if (tmp2) {
  554.                 result = BuildTreeNode(PTF_ifthenelse_stmt, tmp, result, tmp2);
  555.                 } else {
  556.                 SyntaxError("Expected statement following else");
  557.                 }
  558.             } else {
  559.                 result = BuildTreeNode(PTF_ifthenelse_stmt, tmp, result, NULL);
  560.             }
  561.             } else {
  562.             SyntaxError("Expected statement following if");
  563.             }
  564.         } else {
  565.             SyntaxError("Missing right parenthesis");
  566.         }
  567.         } else {
  568.         SyntaxError("Expected expr for if conditional");
  569.         }
  570.     } else {
  571.         SyntaxError("if keyword must be followed by a left paren");
  572.     }
  573.     } else if (NextIs(SWITCH)) {
  574.     ParseTreeVia_t                  oldLastSwitch = NULL;
  575.     if (NextIs('(')) {
  576.         tmp = Do_expr();
  577.         if (tmp) {
  578.         ConstExprValue(tmp, &testK);
  579.         if (testK.isK) {
  580.             UserWarning(WARN_constantswitch);
  581.         }
  582.         if (!isIntegralType(GetTreeTP(tmp))) {
  583.             UserWarning(WARN_nonintegralswitch);
  584.         }
  585.         oldLastSwitch = LastSwitchExpression;
  586.         LastSwitchExpression = tmp;
  587.         if (NextIs(')')) {
  588.             result = Do_statement();
  589.             if (result) {
  590.             result = BuildTreeNode(PTF_switch_stmt, tmp, result, NULL);
  591.             } else {
  592.             SyntaxError("Expected statement after switch (cond)");
  593.             }
  594.         } else {
  595.             SyntaxError("Missing right parenthesis");
  596.         }
  597.         } else {
  598.         SyntaxError("Expected expression for switch");
  599.         }
  600.     } else {
  601.         SyntaxError("switch must be followed by a paren");
  602.     }
  603.     LastSwitchExpression = oldLastSwitch;
  604.     } else {
  605.     result = NULL;
  606.     }
  607.     return result;
  608. }
  609.  
  610. ParseTreeVia_t
  611. Do_iteration_statement(void)
  612. {
  613.     /*
  614.      * iteration_statement : WHILE '(' expr ')' statement | DO statement
  615.      * WHILE '(' expr ')' ';' | FOR '(' ';' ';' ')' statement | FOR '(' ';'
  616.      * ';' expr ')' statement | FOR '(' ';' expr ';' ')' statement | FOR '('
  617.      * ';' expr ';' expr ')' statement | FOR '(' expr ';' ';' ')' statement |
  618.      * FOR '(' expr ';' ';' expr ')' statement | FOR '(' expr ';' expr ';'
  619.      * ')' statement | FOR '(' expr ';' expr ';' expr ')' statement ;
  620.      */
  621.  
  622.     ParseTreeVia_t                  result = NULL;
  623.     ParseTreeVia_t                  tmp1;
  624.     ParseTreeVia_t                  tmp2;
  625.     ParseTreeVia_t                  tmp3;
  626.     ParseTreeVia_t                  other;
  627.     FoldValue_t                     testK;
  628.     if (NextIs(WHILE)) {
  629.     FunctionComplexity++;
  630.     if (NextIs('(')) {
  631.         tmp1 = Do_expr();
  632.         if (tmp1) {
  633.         if (!isBooleanType(GetTreeTP(tmp1))) {
  634.             TypeError("while expression must be arithmetic or pointer type");
  635.         }
  636.         ConstExprValue(tmp1, &testK);
  637.         if (testK.isK) {
  638.             UserWarning(WARN_constantwhile);
  639.         }
  640.         if (NextIs(')')) {
  641.             tmp2 = Do_statement();
  642.             if (tmp2) {
  643.             result = BuildTreeNode(PTF_while_stmt, tmp1, tmp2, NULL);
  644.             } else {
  645.             SyntaxError("Expected statement for while loop");
  646.             }
  647.         } else {
  648.             SyntaxError("Missing right parenthesis");
  649.         }
  650.         } else {
  651.         SyntaxError("Expected expression for while loop");
  652.         }
  653.     } else {
  654.         SyntaxError("while must be followed by a left parenthesis");
  655.     }
  656.     } else if (NextIs(DO)) {
  657.     tmp1 = Do_statement();
  658.     if (tmp1) {
  659.         if (NextIs(WHILE)) {
  660.         FunctionComplexity++;
  661.         if (NextIs('(')) {
  662.             tmp2 = Do_expr();
  663.             if (tmp2) {
  664.             ConstExprValue(tmp2, &testK);
  665.             if (testK.isK) {
  666.                 UserWarning(WARN_constantdowhile);
  667.             }
  668.             if (!isBooleanType(GetTreeTP(tmp2))) {
  669.                 TypeError("while expression must be arith or pointer type");
  670.             }
  671.             result = BuildTreeNode(PTF_dowhile_stmt, tmp1, tmp2, NULL);
  672.             if (!NextIs(')')) {
  673.                 SyntaxError("Missing right parenthesis");
  674.             }
  675.             if (!NextIs(';')) {
  676.                 SyntaxError("Missing semicolon");
  677.             }
  678.             } else {
  679.             SyntaxError("Expected expression for do-while");
  680.             }
  681.         } else {
  682.             SyntaxError("Expected left parenthesis");
  683.         }
  684.         } else {
  685.         SyntaxError("Expected while keyword after do statement");
  686.         }
  687.     }
  688.     } else if (NextIs(FOR)) {
  689.     FunctionComplexity++;
  690.     tmp1 = tmp2 = tmp3 = other = NULL;
  691.     if (NextIs('(')) {
  692.         tmp1 = Do_expr();
  693.         if (!NextIs(';')) {
  694.         SyntaxError("Missing semicolon");
  695.         }
  696.         tmp2 = Do_expr();
  697.         if (tmp2) {
  698.         ConstExprValue(tmp2, &testK);
  699.         if (testK.isK) {
  700.             UserWarning(WARN_constantfor);
  701.         }
  702.         if (!isBooleanType(GetTreeTP(tmp2))) {
  703.             TypeError("middle for expression must be arithmetic or pointer type");
  704.         }
  705.         }
  706.         if (!NextIs(';')) {
  707.         SyntaxError("Missing semicolon");
  708.         }
  709.         tmp3 = Do_expr();
  710.         if (!NextIs(')')) {
  711.         SyntaxError("Missing right parenthesis");
  712.         }
  713.         other = Do_statement();
  714.         if (other) {
  715.         result = BuildTreeNode(PTF_for_stmt, tmp1, tmp2, tmp3);
  716.         SetTreeFour(result, other);
  717.         } else {
  718.         SyntaxError("Expected statement for for loop");
  719.         }
  720.     } else {
  721.         SyntaxError("for must be followed by a left parenthesis");
  722.     }
  723.     } else {
  724.     result = NULL;
  725.     }
  726.     return result;
  727. }
  728.  
  729. ParseTreeVia_t
  730. Do_jump_statement(void)
  731. {
  732.     /*
  733.      * jump_statement : GOTO IDENTIFIER ';' | CONTINUE ';' | BREAK ';' |
  734.      * RETURN ';' | RETURN expr ';' ;
  735.      */
  736.  
  737.     ParseTreeVia_t                  result;
  738.     if (NextIs(GOTO)) {
  739.     UserWarning(WARN_goto);
  740.     if (NextIs(IDENTIFIER)) {
  741.         SYMVia_t                        label;
  742.         label = TableSearch(CurrentLabels(), (LastToken));
  743.         if (!label) {
  744.         label = TableAdd(CurrentLabels(), (LastToken));
  745.         }
  746.         result = BuildIDTreeNode(PTF_goto_stmt, NULL, NULL, NULL, LastToken);
  747.         if (!NextIs(';')) {
  748.         SyntaxError("Missing semicolon");
  749.         }
  750.     } else {
  751.         SyntaxError("Expected label after goto");
  752.     }
  753.     } else if (NextIs(CONTINUE)) {
  754.     if (NextIs(';')) {
  755.         result = BuildTreeNode(PTF_continue_stmt, NULL, NULL, NULL);
  756.     } else {
  757.         SyntaxError("Missing semicolon");
  758.     }
  759.     } else if (NextIs(BREAK)) {
  760.     if (NextIs(';')) {
  761.         result = BuildTreeNode(PTF_break_stmt, NULL, NULL, NULL);
  762.     } else {
  763.         SyntaxError("Missing semicolon");
  764.     }
  765.     } else if (NextIs(RETURN)) {
  766.     FunctionReturnCount++;
  767.     if (NextIs(';')) {
  768.         TypeRecordVia_t                 returntypeSB;
  769.         returntypeSB = isFunctionType(GetSymTP(FunctionBeingDefined));
  770.         if (!isVoidType(returntypeSB)) {
  771.         TypeError("return void in non-void valued function");
  772.         }
  773.         result = BuildTreeNode(PTF_return_stmt, NULL, NULL, NULL);
  774.     } else {
  775.         if ((result = Do_expr()) != 0) {
  776.         TypeRecordVia_t                 returntypeSB;
  777.         returntypeSB = isFunctionType(GetSymTP(FunctionBeingDefined));
  778.         ReturnCoerce(returntypeSB, &result);
  779.         if (!SameType(returntypeSB, GetTreeTP(result))) {
  780.             TypeError("type of return expression does not match function type");
  781.         }
  782.         result = BuildTreeNode(PTF_return_stmt, result, NULL, NULL);
  783.         if (!NextIs(';')) {
  784.             SyntaxError("Missing semicolon");
  785.         }
  786.         } else {
  787.         SyntaxError("Missing semicolon");
  788.         }
  789.     }
  790.     } else {
  791.     result = NULL;
  792.     }
  793.     return result;
  794. }
  795.  
  796. ParseTreeVia_t
  797. Do_function_body(SYMVia_t funcname)
  798. {
  799.     /*
  800.      * function_body : compound_statement | declaration_list
  801.      * compound_statement ;
  802.      */
  803.     /*
  804.      * There IS a difference between old style and new style function
  805.      * declarations.  With new style declarations, when the function is
  806.      * called, the arguments are type checked against the parameters. With
  807.      * old style, only the return type of the function is stored in the
  808.      * symbol table, and arguments cannot be type-checked.  In this case,
  809.      * standard rules specify how the arguments are to be promoted before
  810.      * pushing them on the stack.
  811.      */
  812.     /*
  813.      * Within the body of a function, there are three symbol tables for
  814.      * objects in scope.  The first is the local symbol table for the block.
  815.      * (In the case of nested blocks, there may be more than three symbol
  816.      * tables in scope)  The second is the table of arguments to the function
  817.      * (this is stored in the symbol table record for the name of the
  818.      * function.)  The third is the global symbol table.  They should be
  819.      * checked in the order given here. That checking is done in
  820.      * do_postfix_expr().
  821.      */
  822.     ParseTreeVia_t                  result;
  823.     int                             tmp;
  824.     SymListVia_t                    oldstyles;
  825.     int                             protospushed;
  826.     int                             PrevStmtCount;
  827.     extern LabSYMVia_t NextFuncSegment;
  828.     PrevStmtCount = CurrentSRC.StmtCount;
  829.     protospushed = 0;
  830.     FunctionBeingDefined = funcname;
  831.     NextFuncSegment = CurrentSegmentLabel;
  832.     FunctionReturnCount = 0;
  833.     FunctionComplexity = 1;
  834.     if (!isFunctionType(GetSymTP(funcname))) {
  835.     SyntaxError("Malformed declaration");
  836.     return NULL;
  837.     }
  838.     oldstyles = RawTable(11);
  839.     tmp = Do_declaration_list(oldstyles);
  840.     if (tmp && (GetTPKind(GetSymTP(funcname)) != TRC_OLDfunction)) {
  841.     DeclErrorSYM("Inconsistent function declaration", funcname);
  842.     }
  843.     if (tmp) {
  844.     int                             cnt;
  845.     SYMVia_t                        outp;
  846.     cnt = 1;
  847.     /* Modify array and function types as per ANSI */
  848.     while (cnt <= Via(oldstyles)->count) {
  849.         outp = TableGetNum(oldstyles, cnt);
  850.         if (isArrayType(GetSymTP(outp))) {
  851.         SetSymTP(outp, BuildTypeRecord(GetTPBase(GetSymTP(outp)), TRC_pointer, SGN_unknown));
  852.         }
  853.         if (isFunctionType(GetSymTP(outp))) {
  854.         SetSymTP(outp, BuildTypeRecord(GetSymTP(outp), TRC_pointer, SGN_unknown));
  855.         }
  856.         cnt++;
  857.     }
  858.     }
  859.     if (tmp) {
  860.     int                             cnt;
  861.     SYMVia_t                        inp;
  862.     SYMVia_t                        outp;
  863.     char                            nm[64];
  864.     cnt = 1;
  865.     while (cnt <= Via(oldstyles)->count) {
  866.         outp = TableGetNum(oldstyles, cnt);
  867.         GetSymName(outp, nm);
  868.         inp = TableSearch(GetTPMembers(GetSymTP(funcname)), nm);
  869.         if (inp) {
  870.         if (GetSymTP(inp)) {
  871.             if (!SameType(GetSymTP(inp), GetSymTP(outp))) {
  872.             DeclErrorSYM("Inconsistent function declaration", funcname);
  873.             }
  874.         } else {
  875.             SetSymTP(inp, GetSymTP(outp));
  876.         }
  877.         } else {
  878.         DeclError2("Not a parameter : ", nm);
  879.         }
  880.         /*
  881.          * If the members in inp have type associated with them, then
  882.          * this was previously declared ANSI, and we are merely checking
  883.          * for consistency.
  884.          */
  885.         cnt++;
  886.     }
  887.     if (GetTPKind(GetSymTP(funcname)) != TRC_ANSIfunction) {
  888.             cnt = 1;
  889.             while (cnt <= Via(GetTPMembers(GetSymTP(funcname)))->count) {
  890.             inp = TableGetNum(GetTPMembers(GetSymTP(funcname)), cnt);
  891.             if (inp) {
  892.                 if (GetSymTP(inp)) {
  893.                     /* Don't promote args per ANSI if the function
  894.                         is a pascal function. 28 March 1992 */
  895.                 if (!(GetTPFlags(GetSymTP(funcname)) & ISPASCALMASK)) {
  896.                     /* Other possibilities might apply here. */
  897.                     if (GetTPKind(GetSymTP(inp)) == TRC_char) {
  898.                         SetSymTP(inp, BuildTypeRecord(0, TRC_int, SGN_signed));
  899.                     }
  900.                     if (GetTPKind(GetSymTP(inp)) == TRC_short) {
  901.                         SetSymTP(inp, BuildTypeRecord(0, TRC_int, SGN_signed));
  902.                     }
  903.                 }
  904.                 } else {
  905.                 SetSymTP(inp, BuildTypeRecord(0, TRC_int, SGN_signed));
  906.                 }
  907.             }
  908.             cnt++;
  909.             }
  910.     }
  911.     }
  912.     FreeSymbolList(oldstyles, 0);
  913.     result = Do_compound_statement(funcname);
  914.     if (FunctionReturnCount) {
  915.     if (FunctionReturnCount > 1) {
  916.         UserWarning(WARN_multireturn);
  917.     }
  918.     } else {
  919.     if (!(isVoidType(isFunctionType(GetSymTP(FunctionBeingDefined))))) {
  920.         UserWarning(WARN_nonvoidreturn);
  921.     }
  922.     }
  923.     /*
  924.      * If there was a decl list before the compound statement, then this is
  925.      * an old style declaration.
  926.      */
  927.     if (result) {
  928.     CountFunctions++;
  929.     Via(funcname)->Definition.FuncBody = result;
  930.     Via(funcname)->storage_class = SCC_normal;
  931.     if (NextIs(';'))
  932.         UserWarning(WARN_semiafterfunction);
  933.     } else {
  934.     if (tmp)
  935.         SyntaxError("Expected compound statement for function body");
  936.     }
  937.     FunctionBeingDefined = NULL;
  938.     return result;
  939. }
  940.